import 'package:flutter/material.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'dart:io';

import 'package:path_provider/path_provider.dart';

/// https://pub.flutter-io.cn/packages/flutter_inappwebview/example
/// https://inappwebview.dev/docs/javascript/communication/

class CommonWebPage extends StatefulWidget {
  @override
  _CommonWebPageState createState() => new _CommonWebPageState();
}

class _CommonWebPageState extends State<CommonWebPage> {

  late BuildContext mContext;
  late String _localPath;

  late String jsStr ;
  late InAppWebViewController webController;
  WebMessagePort? appAndJsPort;

  final GlobalKey webViewKey = GlobalKey();
  InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
      crossPlatform: InAppWebViewOptions(
        useShouldOverrideUrlLoading: true,
        javaScriptEnabled: true,
        useOnLoadResource: true,
        useOnDownloadStart: true,
        mediaPlaybackRequiresUserGesture: false,
      ),
      android: AndroidInAppWebViewOptions(
        useHybridComposition: true,
      ),
      ios: IOSInAppWebViewOptions(
        allowsInlineMediaPlayback: true,
      ));

  @override
  void initState() {
    super.initState();
    _initData();
    _init();
  }

  _init() async {
    if (Platform.isAndroid) {
      await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
    }

    _prepareSaveDir();
  }

  _initData(){
    jsStr = '''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<br />
<br />
<br />
<input id="input" type="text" value="JavaScript To App"/>
<br />
<button onclick="sendToApp(input.value.toString())" />发送</button>
<br />
<br />
<br />
<span >接收到APP的消息:</span>
<br />
<span id="text"></span>
<br />
<br />
<br />
<br />
<br />
<br />
<a href="http://gdown.baidu.com/data/wisegame/0d5a2f3c0e6b889c/qunaerlvxing_146.apk" download="qunaerlvxing_146.apk">下载</a>
<br />
<br />
<br />
<img src="https://www.baidu.com/img/bd_logo1.png" width="270" height="130">

<script>
    let appAndJsPort;
    window.addEventListener('message', function(event) {
        console.log('收到message: '+event.data);
        if (event.data === 'capturePort' && event.ports[0] != null && event.ports[0] !== undefined) {
            appAndJsPort = event.ports[0];
            appAndJsPort.onmessage = function (event) {
                receiveFromApp(event.data);
            };
        }
    }, false);

    function sendToApp(msg){
        console.log('发送到app: '+msg);
        if (appAndJsPort==null && appAndJsPort===undefined) {
            return;
        }
        appAndJsPort.postMessage(msg);
    }

    function receiveFromApp(msg){
        console.log('收到app: '+msg);
        document.getElementById('text').innerHTML  = msg;
    }

</script>
</body>
</html>
    ''';
  }

  @override
  Widget build(BuildContext context) {
    mContext = context;
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(title: Text("Web Message Channels")),
          body: SafeArea(
              child: Column(children: <Widget>[
                Expanded(
                  child: InAppWebView(
                    key: webViewKey,
                    // initialFile: "images/web.html",
                    initialData: InAppWebViewInitialData(data: jsStr),
                    initialOptions: options,
                    onWebViewCreated: (controller) async {
                      print('onWebViewCreated: ');
                      webController = controller;
                    },
                    onConsoleMessage: (controller, consoleMessage) {
                      print("js打印: ${consoleMessage.message}");
                    },
                    onLoadStart: (controller, url) async {
                      print('onLoadStart: '+url.toString());
                    },
                    onLoadStop: (controller, url) async {
                      print('onLoadStop: '+url.toString());
                      initChannel();
                    },
                    onLoadResource: (controller, LoadedResource resource) async {
                      print('onLoadResource: '+resource.url.toString());
                    },
                    onDownloadStart: (controller, url) async {
                      print('onDownloadStart: '+url.toString());

                    },
                    onLongPressHitTestResult: (controller, hitTestResult){
                      print('onLongPressHitTestResult: type=${hitTestResult.type},extra=${hitTestResult.extra}');
                      if(hitTestResult.type == InAppWebViewHitTestResultType.IMAGE_TYPE || hitTestResult.type == InAppWebViewHitTestResultType.SRC_IMAGE_ANCHOR_TYPE){
                        _downImg(hitTestResult.extra);
                      }
                    },
                  ),
                ),
              ])
          )
      ),
    );
  }

  initChannel() async {
    print('initChannel: ');
    if(appAndJsPort!=null){
      return;
    }
    // TODO 不做判断也可以
    // if (!Platform.isAndroid || await AndroidWebViewFeature.isFeatureSupported(AndroidWebViewFeature.WEB_MESSAGE_LISTENER)) {
      WebMessageChannel? webMessageChannel = await webController.createWebMessageChannel();
      if(webMessageChannel == null){
        return;
      }
      print('initChannel: success');
      appAndJsPort = webMessageChannel.port1;
      await appAndJsPort?.setWebMessageCallback((message) async {
        receiveFromJs(message);
      });
      await webController.postWebMessage(message: WebMessage(data: "welfare_game_interface", ports: [webMessageChannel.port2]), targetOrigin: Uri.parse("*"));
    // }
  }

  receiveFromJs(String? message){
    print("收到js: $message");
    
    sendToJs('i am app');
  }
  
  sendToJs(String? msg){
    print("发送到js: $msg");
    appAndJsPort?.postMessage(WebMessage(data: msg));
  }

  /// 图片长按 对话框下载
  _downImg(String? url){
    showMenu(
      context: mContext,
      position: RelativeRect.fromLTRB(0, 0, 0, 0),
      items: <PopupMenuEntry<String>>[
        PopupMenuItem<String>(
          value: url??'',
          child: Text('保存图片到本地'),
          onTap: (){
            if(url!=null) {

            }
          },
        ),
        PopupMenuItem<String>(
          value: '',
          child: Text('取消'),
        ),
      ],
    );
  }

  _downFile(String url) async {
    final taskId = await FlutterDownloader.enqueue(
      url: url,
      savedDir: _localPath,
      showNotification: true, // show download progress in status bar (for Android)
      openFileFromNotification: true, // click on notification to open downloaded file (for Android)
    );
  }

  Future<void> _prepareSaveDir() async {
    _localPath = (await _findLocalPath())!;
    final savedDir = Directory(_localPath);
    bool hasExisted = await savedDir.exists();
    if (!hasExisted) {
      savedDir.create();
    }
  }

  Future<String?> _findLocalPath() async {
    var externalStorageDirPath;
    // if (Platform.isAndroid) {
    //   try {
    //     externalStorageDirPath = await getTemporaryDirectory();
    //   } catch (e) {
    //     final directory = await getExternalStorageDirectory();
    //     externalStorageDirPath = directory?.path;
    //   }
    // } else if (Platform.isIOS) {
    externalStorageDirPath =
        (await getApplicationDocumentsDirectory()).absolute.path;
    // }
    return externalStorageDirPath;
  }
}